/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package pe.edu.pucp.Simulacion.Controlador;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JTable;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.view.JasperViewer;
import pe.edu.pucp.Maestros.DAO.AeropuertoDAO;
import pe.edu.pucp.Maestros.DAO.MaestoVueloDAO;
import pe.edu.pucp.Modelo.Aeropuerto;
import pe.edu.pucp.Modelo.AeropuertoSim;
import pe.edu.pucp.Modelo.Ciudad;
import pe.edu.pucp.Modelo.Permiso;
import pe.edu.pucp.Modelo.Usuario;
import pe.edu.pucp.Modelo.Vuelo;
import pe.edu.pucp.Modelo.VueloSim;
import pe.edu.pucp.Reportes.DAO.ReporteSaturacionDAO;
import pe.edu.pucp.Simulacion.Interfaz.AmpliacionAeropuerto;
import pe.edu.pucp.Simulacion.Interfaz.NecesidadesAeropuertos;
import pe.edu.pucp.Simulacion.Interfaz.NecesidadesVuelos;
import pe.edu.pucp.Simulacion.Interfaz.SimulacionNecesidades;
import pe.edu.pucp.Simulacion.Vista.SimulacionGUI;
import pe.edu.pucp.Util.MapaHelper.JMapViewer.Coordinate;
import pe.edu.pucp.Util.MapaHelper.JMapViewer.MapMarkerDot;
import pe.edu.pucp.Util.MapaHelper.JMapViewer.MapPolygonImpl;
import pe.edu.pucp.Util.Reportclass.Simuaero;
import pe.edu.pucp.Util.Reportclass.SimuaeroDataSource;
import pe.edu.pucp.Util.Reportclass.Simvuelo;
import pe.edu.pucp.Util.Reportclass.SimvueloDataSource;
import pe.edu.pucp.Util.ResultadoSimulacionGUI;
import pe.edu.pucp.Util.ValHelper;
import pe.edu.pucp.sigepa.simulacion.interfaz.EntradaNucleoSimulador;
import pe.edu.pucp.sigepa.simulacion.nucleo.NucleoSimulador;

/**
 *
 * @author katy
 */
public class SimulacionControlador {
    private SimulacionGUI view;
    private ArrayList<Aeropuerto> lstAeropuerto;
    private ArrayList<Vuelo> lstVuelos;
    private ArrayList<AeropuertoSim>  resAeropuertos;          
    private ArrayList<VueloSim>  resVuelos; 
    private ArrayList<Simuaero> ListaImprimirAeropuerto = new ArrayList<>();;
    private ArrayList<Simvuelo> ListaImprimirVuelo = new ArrayList<>();
    private ArrayList<Aeropuerto> lstTodos; 
    private NecesidadesAeropuertos necesidadesAeropuertos;
    private NecesidadesVuelos necesidadesAVuelo;
    private static final long serialVersionUID = 1L;
    private double satAeropuertos;
    private double satVuelos;
    private String path;
   
    public SimulacionControlador(double satAeropuertos, double satVuelos,AeropuertoDAO dao, ArrayList<Aeropuerto> listaAeropuetos, SimulacionGUI sview, Usuario usr,  String pathParam, ArrayList<Vuelo> listaVuelos) {
        lstTodos = dao.listarAeropuertos(null, null, false);
        this.path = pathParam;
        this.satAeropuertos = satAeropuertos;
        this.satVuelos = satVuelos;
        this.lstAeropuerto = listaAeropuetos;
        this.lstVuelos = listaVuelos;
        this.view = sview;
        
        view.mostrarPermisos(new  ArrayList<Permiso>(usr.getPerfil().getPermisos())); 
        if (lstVuelos == null) {
             view.setDatosLeyenda(this.satAeropuertos, this.satVuelos, lstAeropuerto.size(), 0);
        }
        else 
            view.setDatosLeyenda(this.satAeropuertos, this.satVuelos, lstAeropuerto.size(), lstVuelos.size());
        view.addSimulacionBtnListener(new SimulacionListener(this));
        view.addTableListener(new TblListener());
        view.addTableKeyListener(new TblKeyListener());
        view.addTablaVuelosListenert(new TblVuelosListener());
        view.addCancelarBtnListener(new CancelarListener());
        view.addMostrarPdfListener(new MostrarPDF());
        //Llenar la grilla de aeropuertos
        llenarAeropuertos(lstAeropuerto);
        dibujarAeropuertos(lstTodos, Color.YELLOW);
        dibujarAeropuertos(lstAeropuerto,Color.RED);
       
    }

    public void actualizarMapaVuelos(JTable tbl, ArrayList<Vuelo> lst) {
        Vuelo v ;
        try {
            int i = tbl.getSelectedRow();
            if (i>0 && lst!=null) {
                view.getMapa().removeAllMapPolygons();
                v = lst.get(i);
                Coordinate cInicio = new Coordinate(v.getAeropuertoByIdorigen().getCiudad().getLatitud(), v.getAeropuertoByIdorigen().getCiudad().getAltitud());
                Coordinate cFin = new Coordinate(v.getAeropuertoByIddestino().getCiudad().getLatitud(), v.getAeropuertoByIddestino().getCiudad().getAltitud());
            List<Coordinate> ruta = new ArrayList<>(Arrays.asList(cInicio, cFin,cInicio));
            view.getMapa().addMapPolygon(new MapPolygonImpl(ruta));
                MapMarkerDot m = new MapMarkerDot(v.getAeropuertoByIdorigen().getCiudad().getLatitud(), v.getAeropuertoByIdorigen().getCiudad().getAltitud(), Color.YELLOW);
                view.getMapa().addMapMarker(m);
                m = new MapMarkerDot(v.getAeropuertoByIddestino().getCiudad().getLatitud(), v.getAeropuertoByIddestino().getCiudad().getAltitud(), Color.YELLOW);
                view.getMapa().addMapMarker(m);
                view.setDisplayPositionByLatLon(v.getAeropuertoByIdorigen().getCiudad().getLatitud(), v.getAeropuertoByIdorigen().getCiudad().getAltitud());
            }
        }
        catch(Exception e){
            e.printStackTrace();
        }
        view.getMapa().repaint();
    }
    
    public void actualizarMapa(JTable tbl,ArrayList<Aeropuerto> lst) {
        try {
                Aeropuerto  a = lstAeropuerto.get(tbl.getSelectedRow());
                Color color = Color.RED;
                int nuevaCapacidad = Integer.parseInt(tbl.getValueAt(tbl.getSelectedRow(), 2).toString());
                if ((nuevaCapacidad + a.getCappack()) != a.getCappack())
                    color = Color.GREEN;
                ArrayList<Aeropuerto> l =  new ArrayList<Aeropuerto>();
                l.add(a);
               
                dibujarAeropuertos(l, color);
                dibujaVuelosSalientes(a);
                view.setDisplayPositionByLatLon(a.getCiudad().getLatitud(), a.getCiudad().getAltitud());
        } catch(Exception ex) {
               ex.printStackTrace();
        }
    }
    

    private void dibujaVuelosSalientes(Aeropuerto a) {
        ArrayList<Vuelo> lstVuelos = (new MaestoVueloDAO()).ListarVuelosDeUnAeropuerto(a.getIdaeropuerto());
        Coordinate cInicio = new Coordinate(a.getCiudad().getLatitud(), a.getCiudad().getAltitud());
        view.getMapa().removeAllMapPolygons();
        for (int i=0; i<lstVuelos.size();i++) {
        
            Coordinate cFin = new Coordinate(lstVuelos.get(i).getAeropuertoByIddestino().getCiudad().getLatitud(), lstVuelos.get(i).getAeropuertoByIddestino().getCiudad().getAltitud());
            List<Coordinate> ruta = new ArrayList<>(Arrays.asList(cInicio, cFin,cInicio));
            view.getMapa().addMapPolygon(new MapPolygonImpl(ruta));
        }
    }
    
    private void dibujarAeropuertos(ArrayList<Aeropuerto> lst, Color color) {
        if(lst != null) {
            MapMarkerDot m;
            for(int j=0; j<lst.size(); j++)
            {
                Ciudad ciudad = lst.get(j).getCiudad();
                
                m = new MapMarkerDot(ciudad.getLatitud(), ciudad.getAltitud(), color);
                view.getMapa().addMapMarker(m);
            }
        } else {
        }
    }
    
    public NecesidadesAeropuertos getModificacionesAeropuertos() {
        JTable tbl = view.getTblAeroppuertos();
        NecesidadesAeropuertos result = new NecesidadesAeropuertos();
        AmpliacionAeropuerto ampliacion;
        for(int i=0; i<tbl.getRowCount(); i++)
        {
            int incremento = Integer.parseInt(tbl.getValueAt(i,2).toString());
            if(incremento > 0) {
                ampliacion = new AmpliacionAeropuerto();
                ampliacion.setAeropuertoOrigenId(lstAeropuerto.get(i).getIdaeropuerto());
                ampliacion.setCapacidadFinal(lstAeropuerto.get(i).getCappack() + incremento);
                result.add(ampliacion);
            }
        }
        return result;
    }
    
    public NecesidadesVuelos getModificacionesVuelos() {
        NecesidadesVuelos listaTabla = view.getTblVuelosNecesidades();
        necesidadesAVuelo = new NecesidadesVuelos();
        ArrayList<Vuelo> lstVuelos = view.getLstVuelos();
        for (int j=0 ; j< lstVuelos.size(); j++) {
                if(lstVuelos.get(j).getAvion().getTipoAvion().getIdtipo() != listaTabla.get(j).getTipoAvionFinalId())
                    necesidadesAVuelo.add(listaTabla.get(j));
        }

        return necesidadesAVuelo;
    }

    //Inicia llenado de grilla Aeropuertos en GUI
    private void llenarAeropuertos(ArrayList<Aeropuerto> listaAeropuertos) {
         view.llenaAeropuertos(listaAeropuertos);
    }
    
    class CancelarListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent e) {
            view.dispose();
        }
        
    }
    
    class TblListener implements  MouseListener {

        @Override
        public void mouseClicked(MouseEvent e) {
            JTable tbl = (JTable)e.getSource();
            actualizarMapa(tbl,lstAeropuerto);
          
       }

        @Override
        public void mousePressed(MouseEvent e) {
            e.consume();
            view.getMapa().repaint();
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            e.consume();
            view.getMapa().repaint();

        }

        @Override
        public void mouseEntered(MouseEvent e) {
            e.consume();
            view.getMapa().repaint();

        }

        @Override
        public void mouseExited(MouseEvent e) {
            e.consume();
            view.getMapa().repaint();

        }
    
    }
    
    class TblKeyListener implements KeyListener { 
        SimulacionControlador controlador;
        @Override
        public void keyTyped(KeyEvent e) {
          e.consume();
            view.getMapa().repaint();

        }

        @Override
        public void keyPressed(KeyEvent e) {
            JTable tbl = (JTable)e.getSource();
            try {
                Aeropuerto  a = lstAeropuerto.get(tbl.getSelectedRow());
                ArrayList<Aeropuerto> l = new ArrayList<Aeropuerto>();
                l.add(a);
                dibujarAeropuertos(l, Color.RED);
                dibujaVuelosSalientes(a);
                view.setDisplayPositionByLatLon(a.getCiudad().getLatitud(), a.getCiudad().getAltitud());
            } catch(Exception ex) {
               ex.printStackTrace();
            }
            view.getMapa().repaint();

        }

        @Override
        public void keyReleased(KeyEvent e) {
           e.consume();
            view.getMapa().repaint();

        }
    }
    
    class TblVuelosListener implements MouseListener {

        @Override
        public void mouseClicked(MouseEvent e) {
             JTable tbl = (JTable)e.getSource();
            actualizarMapaVuelos(tbl,lstVuelos);
            
        }

        @Override
        public void mousePressed(MouseEvent e) {
             e.consume();
            view.getMapa().repaint();

        }

        @Override
        public void mouseReleased(MouseEvent e) {
            e.consume();
            view.getMapa().repaint();
        }

        @Override
        public void mouseEntered(MouseEvent e) {
              e.consume();
            view.getMapa().repaint();

        }

        @Override
        public void mouseExited(MouseEvent e) {
             e.consume();
            view.getMapa().repaint();

        }
    
    }
    
    class SimulacionListener implements ActionListener {
        SimulacionControlador controlador;
        
        public  SimulacionListener (SimulacionControlador controlador) 
        {
         
            this.controlador = controlador;
        }
        
        @Override
        public void actionPerformed(ActionEvent e) {
            view.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
            SimulacionNecesidades simulacionNecesidades = new SimulacionNecesidades(controlador);
            EntradaNucleoSimulador entradaNucleoSimulador = new EntradaNucleoSimulador();

            if (simulacionNecesidades.getAeropuertos().size()==0 || simulacionNecesidades.getVuelos().size() ==0)
            {
                ValHelper.mostrarAviso("No se ha modificado ninguna capacidad de vuelo o aeropuerto.");
                return;
            }
            
            necesidadesAeropuertos = simulacionNecesidades.getAeropuertos();
            NecesidadesVuelos necesidadesVuelos = simulacionNecesidades.getVuelos();
            
            for (pe.edu.pucp.Simulacion.Interfaz.AmpliacionAeropuerto ampliacionAeropuerto : necesidadesAeropuertos) {
                
                entradaNucleoSimulador.agregarAmpliacionAeropuerto(
                new pe.edu.pucp.sigepa.simulacion.interfaz.AmpliacionAeropuerto(ampliacionAeropuerto.getAeropuertoOrigenId(), ampliacionAeropuerto.getCapacidadFinal()));        
            }
            
            for (pe.edu.pucp.Simulacion.Interfaz.AmpliacionVuelo ampliacionVuelo : necesidadesVuelos) {
            entradaNucleoSimulador.agregarAmpliacionVuelo(
                        new pe.edu.pucp.sigepa.simulacion.interfaz.AmpliacionVuelo(ampliacionVuelo.getAeropuertoOrigenId(), ampliacionVuelo.getAeropuertoDestinoId(), ampliacionVuelo.getTipoAvionFinalId()));
            }
        
            try {
                new NucleoSimulador().iniciarSimulacion(entradaNucleoSimulador);            
            } catch (ParseException ex) {
                Logger.getLogger(SimulacionControlador.class.getName()).log(Level.SEVERE, null, ex);
            }
            
            try {
                resAeropuertos = ( new ReporteSaturacionDAO()).ConsultaObtenerSaturacionSimulacion(2012,03, 2013, 12, satAeropuertos);
                resVuelos = (new ReporteSaturacionDAO()).ConsultaSaturacionVuelosSimulacion(2012,03,2013, 13,satVuelos);
                System.out.println("Aeropuertos después:" + resAeropuertos.size());
                System.out.println("Vuelos después:" + resVuelos.size());
            } catch(Exception exr) {
                System.out.println(exr.getMessage());
            }
           
            actualizarMapa(view.getTblAeroppuertos(), lstAeropuerto);
            view.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
            
          try {
            ResultadoSimulacionGUI simulacionResultado = new ResultadoSimulacionGUI(view, false, resAeropuertos);
            simulacionResultado.setVisible(true);
          }catch(Exception ex) {
              ex.printStackTrace();
          }
          view.getMapa().repaint();
        }

    }
    
    
    class MostrarPDFvuelo implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
        
//            for(Vuelo a :lstVuelos)
//            {
//                for(int i=0;i<necesidadesAVuelo.size();i++)
//                {
//                    if(a.getAeropuertoByIddestino().getIdaeropuerto()==necesidadesAVuelo.get(i).getAeropuertoDestinoId() && a.getAeropuertoByIdorigen().getIdaeropuerto()==necesidadesAVuelo.get(i).getAeropuertoOrigenId())
//                    {
//                        // en esta parte no hay manera de sacar la saturacion nueva
//                        Simvuelo s = new Simvuelo(a.getAeropuertoByIdorigen().getDescripcion(),a.getAeropuertoByIddestino().getDescripcion(),a.getNumpack(),a.getNumpack()/a.getCosto(),b.getNumpack(),b.getNumpack()/b.getCosto());
//                        ListaImprimirVuelo.add(s);
//                    }
//                }
//            }
//            
//            SimvueloDataSource datasource = new SimvueloDataSource();            
//                    for (int i=0;i<ListaImprimirVuelo.size();i++){                
//                        datasource.addSimuaero(ListaImprimirVuelo.get(i));                
//                } 
//                    
//                JasperReport reporte = null;                
//                try {
//                    reporte = (JasperReport)JRLoader.loadObjectFromFile("SimuVuelo.jasper");
//                } catch (JRException ex) {
//                    Logger.getLogger(SimulacionControlador.class.getName()).log(Level.SEVERE, null, ex);
//                }
//                    JasperPrint jasperPrint = null;             
//                try {
//                    jasperPrint = JasperFillManager.fillReport(reporte, null, datasource);
//                } catch (JRException ex) {
//                    Logger.getLogger(SimulacionControlador.class.getName()).log(Level.SEVERE, null, ex);
//                }
//                    JasperViewer.viewReport(jasperPrint,false);
            
            
    }
    }
    
    
    class MostrarPDF implements ActionListener {

        @Override
    public void actionPerformed(ActionEvent e) {
                       
           for(Aeropuerto a :lstAeropuerto)
           {
                for (AmpliacionAeropuerto ampliacion : necesidadesAeropuertos) {
                 
                    if (a.getIdaeropuerto() == ampliacion.getAeropuertoOrigenId())
                    {
                        for(AeropuertoSim b: resAeropuertos)
                        {
                            if(a.getIdaeropuerto()==b.getIdaeropuerto())
                            {
                                Simuaero s = new Simuaero(a.getDescripcion(),a.getCappack(), a.getCostpack(), ampliacion.getCapacidadFinal(), b.getCostpack());
                                ListaImprimirAeropuerto.add(s);
                            }
                        }     
                    }
                    else
                    {
                        Simuaero s = new Simuaero(a.getDescripcion(),a.getCappack(), a.getCostpack(), a.getCappack(), a.getCostpack());
                        ListaImprimirAeropuerto.add(s);
                     
                    }
                }
            }
            
            for(Vuelo a :lstVuelos)
            {
                for(VueloSim b: resVuelos)
                {
                    if(a.getIdvuelo()==b.getIdvuelo())
                    {
                       if(a.getCosto()!=b.getCosto())
                       {
                            Simvuelo s = new Simvuelo(a.getAeropuertoByIdorigen().getDescripcion(),a.getAeropuertoByIddestino().getDescripcion(),a.getNumpack(),a.getNumpack()/a.getCosto(),b.getNumpack(),b.getNumpack()/b.getCosto());
                            ListaImprimirVuelo.add(s);
                       }
                    }
                    else
                    {
                        continue;
                    }
                }
            }
            
            //ACA TERMINA LA PARTE
            //CAYCHO LOS ARREGLOS QUE NECESITAS SON ListaImprimirVuelo Y ListaImprimirAeropuerto
           
            if (resAeropuertos != null && resAeropuertos.size()>0 && resVuelos != null && resVuelos.size()>0){
                SimuaeroDataSource datasource = new SimuaeroDataSource();  
                
                    System.out.println("tam:" + ListaImprimirAeropuerto.size());
                    for (int i=0;i<ListaImprimirAeropuerto.size();i++){     
                       
                    datasource.addSimuaero(ListaImprimirAeropuerto.get(i));                
                } 
                    
                JasperReport reporte = null;                
                try {
                    String master = System.getProperty("user.dir");
                    master += "/../SIGEPA_sist/src/main/resources/Recurso/jasper/SimuAeropuerto.jasper";
                    reporte = (JasperReport)JRLoader.loadObjectFromFile(master);
                } catch (JRException ex) {
                    Logger.getLogger(SimulacionControlador.class.getName()).log(Level.SEVERE, null, ex);
                }
                    JasperPrint jasperPrint = null;             
                try {
                    jasperPrint = JasperFillManager.fillReport(reporte, null, datasource);
                } catch (JRException ex) {
                    Logger.getLogger(SimulacionControlador.class.getName()).log(Level.SEVERE, null, ex);
                }
                    JasperViewer.viewReport(jasperPrint,false);
              
            } else{
                ValHelper.mostrarAlerta("No existen datos para generar el pdf.");
            }
            
            view.getMapa().repaint();
        }
    }
}
